﻿using Goway.Log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace Goway.StackingHelper.Inovance
{
    public class HC_MODBUSTCP
    {
        public enum SoftElemType
        {
            //AM600
            ELEM_QX = 0,     //QX元件
            ELEM_MW = 1,     //MW元件
            ELEM_X = 2,      //X元件(对应QX200~QX300)
            ELEM_Y = 3,      //Y元件(对应QX300~QX400)

            //H3U
            REGI_H3U_Y = 0x20,      // Y元件的定义	
            REGI_H3U_X = 0x21,      // X元件的定义							
            REGI_H3U_S = 0x22,      // S元件的定义				
            REGI_H3U_M = 0x23,      // M元件的定义							
            REGI_H3U_TB = 0x24,     // T位元件的定义				
            REGI_H3U_TW = 0x25,     // T字元件的定义				
            REGI_H3U_CB = 0x26,     // C位元件的定义				
            REGI_H3U_CW = 0x27,     // C字元件的定义				
            REGI_H3U_DW = 0x28,     // D字元件的定义				
            REGI_H3U_CW2 = 0x29,    // C双字元件的定义
            REGI_H3U_SM = 0x2a,     // SM
            REGI_H3U_SD = 0x2b,     //
            REGI_H3U_R = 0x2c,      //
                                    // H5u
            REGI_H5U_Y = 0x30,      // Y元件的定义	
            REGI_H5U_X = 0x31,      // X元件的定义							
            REGI_H5U_S = 0x32,      // S元件的定义				
            REGI_H5U_M = 0x33,      // M元件的定义	
            REGI_H5U_B = 0x34,      // B元件的定义
            REGI_H5U_D = 0x35,      // D字元件的定义
            REGI_H5U_R = 0x36,      // R字元件的定义
        }

        #region //标准库
        [DllImport("StandardModbusApi.dll", EntryPoint = "Init_ETH_String", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool Init_ETH_String(string sIpAddr, int nNetId = 0, int IpPort = 502);

        [DllImport("StandardModbusApi.dll", EntryPoint = "Exit_ETH", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool Exit_ETH(int nNetId = 0);

        [DllImport("StandardModbusApi.dll", EntryPoint = "H5u_Write_Soft_Elem", CallingConvention = CallingConvention.Cdecl)]
        public static extern int H5u_Write_Soft_Elem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0);

        [DllImport("StandardModbusApi.dll", EntryPoint = "H5u_Read_Soft_Elem", CallingConvention = CallingConvention.Cdecl)]
        public static extern int H5u_Read_Soft_Elem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0);

        [DllImport("StandardModbusApi.dll", EntryPoint = "H5u_Read_Device_Block", CallingConvention = CallingConvention.Cdecl)]
        public static extern int H5u_Read_Device_Block(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="eType">Stacking数据类型</param>
        /// <param name="nStartAddr">开始地址</param>
        /// <param name="nCount">长度</param>
        /// <param name="pValue">字符数组</param>
        /// <param name="nNetId"></param>
        /// <returns></returns>
        [DllImport("StandardModbusApi.dll", EntryPoint = "H5u_Write_Device_Block", CallingConvention = CallingConvention.Cdecl)]
        public static extern int H5u_Write_Device_Block(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0);

        #endregion

        public static int Read(int stratAddr, int length, string Type, int nDataType, ref object[] ints)
        {
            //缓冲区。读取整型字元件则一个元件占两个byte，位元件则占一个byte。例如读取D元件500个，则缓冲区大小为1000以上
            try
            {
                byte[] pBuf = new byte[length * 2];
                int nStartAddr = Convert.ToInt32(stratAddr);
                int nCount = Convert.ToInt32(length);
                bool bIsWord = false;//是否字元件
                HC_MODBUSTCP.SoftElemType ElemType = HC_MODBUSTCP.SoftElemType.REGI_H5U_Y;
                switch (Type)
                {
                    case "Y":
                        ElemType = HC_MODBUSTCP.SoftElemType.REGI_H5U_Y;
                        break;
                    case "X":

                        ElemType = HC_MODBUSTCP.SoftElemType.REGI_H5U_X;
                        break;
                    case "S":
                        ElemType = HC_MODBUSTCP.SoftElemType.REGI_H5U_S;
                        break;
                    case "M":
                        ElemType = HC_MODBUSTCP.SoftElemType.REGI_H5U_M;
                        break;
                    case "B":
                        ElemType = HC_MODBUSTCP.SoftElemType.REGI_H5U_B;
                        break;
                    case "D":
                        bIsWord = true;
                        ElemType = HC_MODBUSTCP.SoftElemType.REGI_H5U_D;
                        break;
                    case "R":
                        bIsWord = true;
                        ElemType = HC_MODBUSTCP.SoftElemType.REGI_H5U_R;
                        break;
                }

                int nRet = HC_MODBUSTCP.H5u_Read_Device_Block(ElemType, nStartAddr, nCount, pBuf, 0);
                if (nRet != 1)
                {
                    InsertNote(DateTime.Now.ToString() + "：ErrorCode " + nRet.ToString() + "\r\n");
                }

                string strData = "";
                if (nDataType == 1 || nDataType == 2)
                {
                    nCount = nCount / 2;
                }
                for (int i = 0; i < nCount; i++)
                {
                    if (bIsWord)
                    {
                        if (nDataType == 0)//16位整形
                        {
                            byte[] databuf = new byte[2] { 0, 0 };
                            databuf[0] = pBuf[i * 2];
                            databuf[1] = pBuf[i * 2 + 1];
                            int iTemp = BitConverter.ToInt16(databuf, 0);
                            strData = strData + iTemp.ToString() + " ";

                        }
                        else if (nDataType == 1)//读取32位整形
                        {
                            byte[] databuf = new byte[4] { 0, 0, 0, 0 };
                            databuf[0] = pBuf[i * 4];
                            databuf[1] = pBuf[i * 4 + 1];
                            databuf[2] = pBuf[i * 4 + 2];
                            databuf[3] = pBuf[i * 4 + 3];
                            int iTemp = BitConverter.ToInt32(databuf, 0);
                            strData = strData + iTemp.ToString() + " ";

                        }
                        else if (nDataType == 2)//读取浮点型
                        {
                            byte[] databuf = new byte[4] { 0, 0, 0, 0 };
                            databuf[0] = pBuf[i * 4];
                            databuf[1] = pBuf[i * 4 + 1];
                            databuf[2] = pBuf[i * 4 + 2];
                            databuf[3] = pBuf[i * 4 + 3];
                            float fTemp = BitConverter.ToSingle(databuf, 0);
                            strData = strData + fTemp.ToString() + " ";

                        }
                    }
                    else
                    {
                        int nVal = 0;
                        nVal = pBuf[i];
                        strData = strData + nVal.ToString() + " ";
                    }
                    //  insertNote(DateTime.Now.ToString() + "读取成功！\r\n" + strData);
                }
                // txtMsg.Text = txtMsg.Text + DateTime.Now.ToString() + "读取成功！\r\n"+ strData;
                //        insertNote(DateTime.Now.ToString() + "读取成功！\r\n" + strData);

                string[] vars = null;


                if (strData.Length > 0)
                {

                    vars = strData.Trim().Split(' ');
                    if (nDataType == 0)//16位整形
                    {
                        for (int i = 0; i < vars.Length; i++)
                        {
                            ints[i] = Convert.ToInt16(vars[i]);
                        }
                    }
                    else if (nDataType == 1)//读取32位整形
                    {
                        for (int i = 0; i < vars.Length; i++)
                        {
                            ints[i] = Convert.ToInt32(vars[i]);
                        }
                    }
                    else if (nDataType == 2)//读取浮点型
                    {
                        for (int i = 0; i < vars.Length; i++)
                        {
                            ints[i] = Convert.ToSingle(vars[i]);
                        }
                    }
                }
                //  return ints;
                return nRet;

            }
            catch (Exception ex)
            {

                LoggerHelper.Error(ex);
                return -1;
            }
        }


        public static int ReadFlot(int stratAddr, int length, string Type, int nDataType, ref object[] ints)
        {
            //缓冲区。读取整型字元件则一个元件占两个byte，位元件则占一个byte。例如读取D元件500个，则缓冲区大小为1000以上
            try
            {
                byte[] pBuf = new byte[length * 2];
                int nStartAddr = Convert.ToInt32(stratAddr);
                int nCount = Convert.ToInt32(length);
                bool bIsWord = false;//是否字元件
                HC_MODBUSTCP.SoftElemType ElemType = HC_MODBUSTCP.SoftElemType.REGI_H5U_Y;
                switch (Type)
                {
                    case "Y":
                        ElemType = HC_MODBUSTCP.SoftElemType.REGI_H5U_Y;
                        break;
                    case "X":

                        ElemType = HC_MODBUSTCP.SoftElemType.REGI_H5U_X;
                        break;
                    case "S":
                        ElemType = HC_MODBUSTCP.SoftElemType.REGI_H5U_S;
                        break;
                    case "M":
                        ElemType = HC_MODBUSTCP.SoftElemType.REGI_H5U_M;
                        break;
                    case "B":
                        ElemType = HC_MODBUSTCP.SoftElemType.REGI_H5U_B;
                        break;
                    case "D":
                        bIsWord = true;
                        ElemType = HC_MODBUSTCP.SoftElemType.REGI_H5U_D;
                        break;
                    case "R":
                        bIsWord = true;
                        ElemType = HC_MODBUSTCP.SoftElemType.REGI_H5U_R;
                        break;
                }

                int nRet = HC_MODBUSTCP.H5u_Read_Device_Block(ElemType, nStartAddr, nCount, pBuf, 0);
                if (nRet != 1)
                {
                    InsertNote(DateTime.Now.ToString() + "：ErrorCode " + nRet.ToString() + "\r\n");
                }
                string strData = "";
                if (nDataType == 1 || nDataType == 2)
                {
                    nCount = nCount / 2;
                }
                for (int i = 0; i < nCount; i++)
                {
                    if (bIsWord)
                    {
                        if (nDataType == 0)//16位整形
                        {
                            byte[] databuf = new byte[2] { 0, 0 };
                            databuf[0] = pBuf[i * 2];
                            databuf[1] = pBuf[i * 2 + 1];
                            int iTemp = BitConverter.ToInt16(databuf, 0);
                            strData = strData + iTemp.ToString() + " ";

                        }
                        else if (nDataType == 1)//读取32位整形
                        {
                            byte[] databuf = new byte[4] { 0, 0, 0, 0 };
                            databuf[0] = pBuf[i * 4];
                            databuf[1] = pBuf[i * 4 + 1];
                            databuf[2] = pBuf[i * 4 + 2];
                            databuf[3] = pBuf[i * 4 + 3];
                            int iTemp = BitConverter.ToInt32(databuf, 0);
                            strData = strData + iTemp.ToString() + " ";

                        }
                        else if (nDataType == 2)//读取浮点型
                        {
                            byte[] databuf = new byte[4] { 0, 0, 0, 0 };
                            databuf[0] = pBuf[i * 4];
                            databuf[1] = pBuf[i * 4 + 1];
                            databuf[2] = pBuf[i * 4 + 2];
                            databuf[3] = pBuf[i * 4 + 3];
                            float fTemp = BitConverter.ToSingle(databuf, 0);
                            strData = strData + fTemp.ToString() + " ";

                        }
                    }
                    else
                    {
                        int nVal = 0;
                        nVal = pBuf[i];
                        strData = strData + nVal.ToString() + " ";
                    }
                    //  insertNote(DateTime.Now.ToString() + "读取成功！\r\n" + strData);
                }
                // txtMsg.Text = txtMsg.Text + DateTime.Now.ToString() + "读取成功！\r\n"+ strData;
                //        insertNote(DateTime.Now.ToString() + "读取成功！\r\n" + strData);

                string[] vars = null;

                if (strData.Length > 0)
                {

                    vars = strData.Trim().Split(' ');

                    for (int i = 0; i < vars.Length; i++)
                    {
                        ints[i] = Convert.ToDouble(vars[i]);
                    }
                }
                //  return ints;
                return nRet;

            }
            catch (Exception ex)
            {

                LoggerHelper.Error(ex);
                return -1;
            }
        }

        public static int Write(int stratAddr, int length, string Type, string invars)
        {
            byte[] pBuf = new byte[length * 2];
            int nStartAddr = Convert.ToInt32(stratAddr);
            int nCount = Convert.ToInt32(length);
            bool bIsWord = false;//是否字元件
            SoftElemType ElemType = SoftElemType.REGI_H5U_Y;
            switch (Type)
            {
                case "Y":
                    ElemType = SoftElemType.REGI_H5U_Y;
                    break;
                case "X":

                    ElemType = SoftElemType.REGI_H5U_X;
                    break;
                case "S":

                    ElemType = SoftElemType.REGI_H5U_S;
                    break;
                case "M":

                    ElemType = SoftElemType.REGI_H5U_M;
                    break;
                case "B":

                    ElemType = SoftElemType.REGI_H5U_B;
                    break;
                case "D":
                    bIsWord = true;
                    ElemType = SoftElemType.REGI_H5U_D;
                    break;
                case "R":
                    bIsWord = true;
                    ElemType = SoftElemType.REGI_H5U_R;
                    break;
            }
            var Data = invars.Split(',');
            GetDataFromUI(pBuf, Data, bIsWord, 0);
            int nRet = H5u_Write_Device_Block(ElemType, nStartAddr, nCount, pBuf, 0);
            if (nRet != 1)
            {
                InsertNote(DateTime.Now.ToString() + "：ErrorCode " + nRet.ToString() + "\r\n");
            }
            else
            {
                // insertNote( DateTime.Now.ToString() + "写入成功！\r\n");
            }

            return nRet;
        }



        private static void GetDataFromUI(byte[] pBuf, string[] arr, bool bIsWord, int nDataType)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                if (arr[i] == string.Empty)
                {
                    break;
                }
                double nVal = Convert.ToDouble(arr[i]);
                if (bIsWord)
                {
                    if (nDataType == 0)//16位整形
                    {
                        int idata = Convert.ToInt16(arr[i]);
                        byte[] dataBuf = new byte[2] { 0, 0 };
                        dataBuf = BitConverter.GetBytes(idata);
                        pBuf[2 * i] = dataBuf[0];
                        pBuf[2 * i + 1] = dataBuf[1];
                    }
                    else if (nDataType == 1)//32位整形
                    {
                        int idata = Convert.ToInt32(arr[i]);
                        byte[] dataBuf = new byte[4] { 0, 0, 0, 0 };
                        dataBuf = BitConverter.GetBytes(idata);
                        pBuf[4 * i] = dataBuf[0];
                        pBuf[4 * i + 1] = dataBuf[1];
                        pBuf[4 * i + 2] = dataBuf[2];
                        pBuf[4 * i + 3] = dataBuf[3];
                    }
                    else if (nDataType == 2)//浮点数
                    {
                        float fdata = Convert.ToSingle(arr[i]);
                        byte[] dataBuf = new byte[4] { 0, 0, 0, 0 };
                        dataBuf = BitConverter.GetBytes(fdata);
                        pBuf[4 * i] = dataBuf[0];
                        pBuf[4 * i + 1] = dataBuf[1];
                        pBuf[4 * i + 2] = dataBuf[2];
                        pBuf[4 * i + 3] = dataBuf[3];
                    }
                }
                else
                {
                    pBuf[i] = (byte)nVal;
                }
            }
        }

        /// <summary>
        /// 写日志
        /// </summary>
        /// <param name="message"></param>
        public static void InsertNote(string message)
        {
            LoggerHelper.Fatal(message);
        }
    }
}
